﻿using System;
using FSM;

namespace Procedure
{
    public sealed class ProcedureManager : IProcedureManager
    {
        private IFsmManager m_FsmManager;
        private IFsm<IProcedureManager> m_ProcedureFsm;

        /// <summary>
        /// 初始化流程管理器的实例
        /// </summary>
        public ProcedureManager()
        {
            m_FsmManager = null;
            m_ProcedureFsm = null;
        }

        internal int Priority
        {
            get { return -2; }
        }

        /// <summary>
        /// 获取当前流程
        /// </summary>
        public ProcedureBase CurrentProcedure
        {
            get
            {
                if (m_ProcedureFsm != null)
                {
                    return m_ProcedureFsm.CurrentState as ProcedureBase;
                }

                throw new Exception("You must initialize procedure first.");
            }
        }

        public float CurrentProcedureDurationTime
        {
            get
            {
                if (m_ProcedureFsm == null)
                    throw new Exception("You must initialize procedure first.");
                return m_ProcedureFsm.CurrentStateDurationTime;
            }
        }

        
        internal void Update(float elapseSeconds, float realElapseSeconds)
        {
            
        }

        /// <summary>
        /// 初始化流程管理器
        /// </summary>
        /// <param name="fsmManager"></param>
        /// <param name="procedures"></param>
        /// <exception cref="Exception"></exception>
        public void Initialize(IFsmManager fsmManager, params ProcedureBase[] procedures)
        {
            if (fsmManager == null)
                throw new Exception("FSM manager is invalid.");

            m_FsmManager = fsmManager;
            m_ProcedureFsm = m_FsmManager.CreateFsm(this, procedures);
        }

        /// <summary>
        /// 启动流程
        /// </summary>
        public void StartProcedure<T>() where T : ProcedureBase
        {
            if (m_ProcedureFsm == null)
                throw new Exception("You must initialize procedure first.");
            m_ProcedureFsm.Start<T>();
        }
        
        /// <summary>
        /// 启动流程
        /// </summary>
        public void StartProcedure(Type procedureType)
        {
            if (m_ProcedureFsm == null)
                throw new Exception("You must initialize procedure first.");
            m_ProcedureFsm.Start(procedureType);
        }
        
        /// <summary>
        /// 检查流程是否存在
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public bool HasProcedure<T>() where T : ProcedureBase
        {
            if (m_ProcedureFsm == null)
                throw new Exception("You must initialize procedure first.");
            return m_ProcedureFsm.HasState<T>();
        }
        
        /// <summary>
        /// 检查流程是否存在
        /// </summary>
        public bool HasProcedure(Type procedureType)
        {
            if (m_ProcedureFsm == null)
                throw new Exception("You must initialize procedure first.");
            return m_ProcedureFsm.HasState(procedureType);
        }
        
        /// <summary>
        /// 获取流程
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public ProcedureBase GetProcedure<T>() where T : ProcedureBase
        {
            if (m_ProcedureFsm == null)
                throw new Exception("You must initialize procedure first.");
            return m_ProcedureFsm.GetState<T>();
        }
        
        /// <summary>
        /// 获取流程
        /// </summary>
        /// <param name="procedureType"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public ProcedureBase GetProcedure(Type procedureType)
        {
            if (m_ProcedureFsm == null)
                throw new Exception("You must initialize procedure first.");
            return (ProcedureBase)m_ProcedureFsm.GetState(procedureType);
        }
    }
}